package com.zy.design.ddd.domain.wallet.entity;

import lombok.NoArgsConstructor;
import lombok.Setter;

import java.math.BigDecimal;

/**
 * @author zhaoyi
 * @date 2021/2/5 15:14
 * 基于充血模型的 DDD 开发模式，轻 Service 重Domain
 * 虚拟钱包领域 职责单一、功能通用
 * 数据和功能在一起
 */
@Setter
@NoArgsConstructor
public class VirtualWallet {

    private Long id;
    private BigDecimal balance = BigDecimal.ZERO;
    //是否允许透支
    private boolean isAllowedOverdraft = true;
    //可用透支额
    private BigDecimal overdraftAmount = BigDecimal.ZERO;
    //冻结额
    private BigDecimal frozenAmount = BigDecimal.ZERO;


    public VirtualWallet(Long preAllocatedId) {
        this.id = preAllocatedId;
    }

    public BigDecimal getBalance() {
        return balance;
    }

    //下面方法只列出了部分.. 其余省略
    // 解冻 入账 等

    /**
     * 下面方法只列出了部分.. 其余省略
     * void unfreeze(BigDecimal amount) 解冻
     * void increaseOverdraftAmount(BigDecimal amount) 增加可用透支额
     */

    //透支  私有方法调用时已经确定过可用透支
    private void decreaseOverdraftAmount(BigDecimal amount) {
        overdraftAmount = overdraftAmount.subtract(amount);
    }

    //冻结
    public void freeze(BigDecimal amount) {
        if (amount == null || BigDecimal.ZERO.compareTo(amount) > 0) {
            throw new RuntimeException("请输入正确的冻结金额");
        }
        if (amount.compareTo(balance) > 0) {
            throw new RuntimeException("冻结金额超出总可用额度");
        }
        frozenAmount = frozenAmount.add(amount);
    }


    //获取可用额度
    public BigDecimal getAvaliableBalance() {
        BigDecimal totalAvaliableBalance = this.balance.subtract(this.frozenAmount);
        if (isAllowedOverdraft) {
            return totalAvaliableBalance.add(overdraftAmount);
        }
        return totalAvaliableBalance;
    }

    //出账
    public void debit(BigDecimal amount) {
        BigDecimal totalAvaliableBalance = getAvaliableBalance();
        if (totalAvaliableBalance.compareTo(amount) < 0) {
            throw new RuntimeException("可用额度不足");
        }
        //余额减去冻结的
        BigDecimal ba = balance.subtract(frozenAmount);
        if (ba.compareTo(amount) < 0) {
            //现金部分不够了
            balance = balance.subtract(ba);
            //透支
            decreaseOverdraftAmount(amount.subtract(ba));

        } else {
            balance = balance.subtract(amount);
        }
    }
    // 入账 credit
    public void credit(BigDecimal amount) {
        System.out.println("入账具体逻辑忽略" + amount);
    }

}
